package com.foreknow.reflection;

import java.awt.*;
import java.lang.reflect.Method;
import java.util.Hashtable;

/**
 * Java反射机制是Java语言中的一个非常重要的特性，它具有动态机制--------反射
 * 反射的特点：
 * 1.在程序运行的时候会判断任意一个对象所属的类
 * 2.在运行的时候获取类的对象
 * 3.在运行的时候获取到类所具有的成员变量和方法
 *
 * 总结：通过运行结果可以发现，Java的反射机制使得在运行时能够判断一个对象所属的类，获取对象的方法并进行调用，并获取方法的返回结果。
 *
 * 实例化Class类对象有以下几种方式
 * 1. 前提：已知是一个具体的类，大家可以通过class属性来获取，这种方法是最安全的，并且性能高
 *    Class clazz = String.class;     Mybatis中获取类对象：UserMapper.class
 * 2.  Button btn = new Button();
 *     Class btnClass = btn.getClass();
 * 3. Class clazz = Class.forName("java.lang.Stlring");
 *
   * 4. ClassLoader cl = this.getClass().getClassLoader();
 *    Class clazz = cl.loadClass("全类名")；
    */
  public class ReflectionDemo {

  public void getNameTest() throws ClassNotFoundException {
    String name="这是一个反射测试";
    Class cls = name.getClass();
    System.out.println("String的类名："+cls.getName());
    Button btn = new Button();
    Class btnClass = btn.getClass();
    System.out.println("Button类名："+btnClass.getName());
    Class superBtnClass = btnClass.getSuperclass();
    System.out.println("Button的父类的名称："+ superBtnClass.getName());
    Class clsTest = Class.forName("java.awt.Button");
    System.out.println("clsTest name:"+clsTest.getName());
  }

  /**
   * 此方法可以通过反射机制去调用testMesthod方法，而无需手动调用
   * @throws Exception
   */
  public void getMethodTest() throws  Exception {
    Class cls = Class.forName("com.foreknow.reflection.ReflectionDemo");
    Class ptypes[] = new Class[2];
    ptypes[0] = Class.forName("java.lang.String");
    ptypes[1] = Class.forName("java.util.Hashtable");
    //此方法是获取到我们想要调用的方法的名称(methodName)以及参数的类型(parameterType)
    Method method = cls.getMethod("testMesthod",ptypes);
    Object[] args = new Object[2];
    args[0] = "hello tom";
    Hashtable<String,String> ht = new Hashtable<String, String>();
    ht.put("name","你好这是一个map");
    args[1] = ht;
    //我们需要调用testMesthod这个方法
    String returnStr = (String) method.invoke(new ReflectionDemo(),args);
    System.out.println("returnStr="+returnStr);
  }

  public String testMesthod(String str, Hashtable ht) throws Exception {
    String returnStr = "这是方法的返回值";
    System.out.println("测试testMethod（）方法调用");
    System.out.println("str="+str);
    System.out.println("名字="+(String)ht.get("name"));
    System.out.println("结束了testMethod()方法的调用");
    return returnStr;
  }

    public static void main(String[] args) throws Exception {
      ReflectionDemo reflectionDemo = new ReflectionDemo();
      reflectionDemo.getMethodTest();
  }

}
